package com.aznest.service.impl;

import com.aznest.context.BaseContext;
import com.aznest.entity.Account;
import com.aznest.entity.Type;
import com.aznest.mapper.OrdersMapper;
import com.aznest.mapper.RoomMapper;
import com.aznest.mapper.TypeMapper;
import com.aznest.service.StatService;
import com.fasterxml.jackson.databind.ser.Serializers;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
@Slf4j
public class StatServiceImpl implements StatService {

    @Resource
    private RoomMapper roomMapper;
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private TypeMapper typeMapper;


    /**
     * 获取基础的酒店统计信息
     * @return
     */
    @Override
    public Map<String, Object> base() {
        Map<String, Object> map = new HashMap<>();
        // 当前酒店信息
        Account currentUser = BaseContext.getCurrentUser();
        Integer hotelId = currentUser.getId();
        // 房间总数
        Integer roomCnt = roomMapper.selectCntByHotelId(hotelId);
        // 当前空房数
        Integer freeRoomCnt = roomMapper.selectByHotelIdWithFree(hotelId);
        // 本月订单总数
        Integer ordersCntCurMonth = ordersMapper.selectCurMonthOrdersCnt();
        // 今日收入
        Double todayIncome = ordersMapper.selectTodayIncome();
        map.put("roomCnt", roomCnt);
        map.put("freeRoomCnt", freeRoomCnt);
        map.put("ordersCntCurMonth", ordersCntCurMonth);
        map.put("todayIncome", todayIncome == null ? 0 : todayIncome);

        return map;
    }

    // 房间类型统计图
    @Override
    public Map<String, Object> loadPieWithTypeAndRoomNum() {
        Map<String, Object> map = new HashMap<>();
        List<Map<String, Object>> list = new ArrayList<>();
        // 处理数据
        // 找出当前酒店所有的房间类型
        Integer hotelId = BaseContext.getCurrentUser().getId();
        List<Type> typeList = typeMapper.selectByHotelId(hotelId);
        // 每种类型对应的房间数量
        for (Type type : typeList) {
            Map<String, Object> item = new HashMap<>();
            item.put("name", type.getName());
            Integer roomCntByTypeId = roomMapper.selectRoomCntByTypeId(type.getId());
            item.put("value", roomCntByTypeId);
            list.add(item);
        }
        // 组装数据
        map.put("text","房间类型统计图（饼图）");
        map.put("subtext", "统计维度：房间类型");
        map.put("name", "房间数量");
        map.put("data", list);
        return map;
    }

    // 当前年份的收入
    @Override
    public Map<String, Object> loadCurYearIncome() {
        Map<String, Object> map = new HashMap<>();
        List<Map<String,Object>> income = ordersMapper.selectCurYearIncome(BaseContext.getCurrentUser().getId());
        List<String> xData = new ArrayList<>();
        List<Object> data = new ArrayList<>();
        // 拼接数据库结果的两列：syear和smonth作为dataAxis数据
        for(Map<String,Object> item : income){
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(item.get("syear"));
            stringBuilder.append("-");
            stringBuilder.append(item.get("smonth"));
            xData.add(stringBuilder.toString());
            data.add(item.get("total_sales"));
        }

        // 组装数据
        map.put("text","近十二个月酒店收入情况统计图（折线图）");
        map.put("subtext", "统计维度：每个月的收入情况（单位：元）");
        map.put("xData",xData);
        map.put("data", data);
        return map;
    }

    // 房间类型订单数量统计图
    @Override
    public Map<String, Object> loadLineWithTypeOrderNum() {
        Map<String, Object> map = new HashMap<>();
        // 获取房间类型
        List<Type> typeList = typeMapper.selectByHotelId(BaseContext.getCurrentUser().getId());
        // 组织x轴数据
        List<String> dataAxis = new ArrayList<>();
        for (Type type : typeList) {
            dataAxis.add(type.getName());
        }
        // 组织y轴数据
        List<Integer> data = new ArrayList<>();
        // 每种类型对应的订单数量
        for (Type type : typeList){
            Integer cnt = ordersMapper.selectTypeOrderNum(type.getId());
            data.add(cnt);
        }
        // 组装数据
        map.put("text","房间类型订单数量统计图（柱状图）");
        map.put("subtext", "统计维度：每种房间类型的订单数量");
        map.put("dataAxis",dataAxis);
        map.put("data", data);
        return map;
    }

    /**
     * 导出运营数据报表
     * @param response
     */
    @Override
    public void exportData(HttpServletResponse response) {
        log.info("正在导出数据报表...");
        // 1. 查询数据库---最近30天的运营数据
        List<Map<String,Object>> res = ordersMapper.curMonthOrders(BaseContext.getCurrentUser().getId());
        // 2. 通过POI写入到Excel文件中
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("template/运营数据模板.xlsx");
        try {
            XSSFWorkbook excel = new XSSFWorkbook(inputStream);
            XSSFSheet sheet = excel.getSheet("Sheet1");
            // 填充酒店名称
            sheet.getRow(1).getCell(1).setCellValue(BaseContext.getCurrentUser().getName());
            // 填充时间
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            sheet.getRow(1).getCell(4).setCellValue(LocalDateTime.now().format(formatter));
            // 填充数据
            for (int i = 0; i < res.size(); i++) {
                Map<String, Object> item = res.get(i);
                sheet.getRow(3 + i).getCell(0).setCellValue(item.get("date").toString());
                sheet.getRow(3 + i).getCell(1).setCellValue(item.get("revenue").toString());
                sheet.getRow(3 + i).getCell(2).setCellValue(item.get("unpaid_orders").toString());
                sheet.getRow(3 + i).getCell(3).setCellValue(item.get("paid_orders").toString());
                sheet.getRow(3 + i).getCell(4).setCellValue(item.get("canceled_orders").toString());
                sheet.getRow(3 + i).getCell(5).setCellValue(item.get("new_users").toString());
            }

            // 通过输出流将Excel文件下载到浏览器
            ServletOutputStream out = response.getOutputStream();
            excel.write(out);
            out.flush();
            // 关闭资源
            out.close();
            excel.close();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
